package pers.luofei.http.client.core;

import pers.luofei.http.client.annotations.GET;
import pers.luofei.http.client.annotations.RequestMapping;
import pers.luofei.http.client.converter.DefaultResponseBodyDecoder;
import pers.luofei.http.client.converter.ResponseBodyDecoder;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by luofei on 2017/8/31.
 */

public class RequestMetaInfo {

    private static final String SPLITER_URL = "/";

    // request fields
    private String id;
    private String name;
    private HttpProtocol protocol;
    private String address;
    private String uri;
    private String method;
    private ContentType contentType;
    private Map<String, String> defaultHeaders;

    // response fields
    private Type returnType;
    private ContentType responseContentType;
    private String decodeNode;
    private ResponseCallback callback;
    private String[] condition;
    private ResponseBodyDecoder decoder;

    public RequestMetaInfo() {
        protocol = HttpProtocol.HTTP;
        uri = "";
        method = GET.NAME;
        contentType = ContentType.FORM_URLENCODED;
        defaultHeaders = new HashMap<>();
        responseContentType = ContentType.JSON;
        callback = DefaultCallback.DEFAULT_CALLBACK;
        decoder = DefaultResponseBodyDecoder.DEFAULT_RESPONSE_BODY_DECODER;
        condition = new String[]{};
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HttpProtocol getProtocol() {
        return protocol;
    }

    public void setProtocol(HttpProtocol protocol) {
        this.protocol = protocol;
    }

    public String getAddress() {

        if (address == null) {
            address = SimpleHttpContext.getDefaultAddress();
        }
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getUri() {
        return uri;
    }

    private String formatUri(String uri) {

        if (uri == null) {
            return "";
        }
        if (uri.startsWith(SPLITER_URL)) {
            uri = uri.substring(1);
        }
        if (!uri.endsWith(SPLITER_URL)) {
            uri += SPLITER_URL;
        }
        return uri;
    }

    public void setUri(String uri) {

        this.uri = formatUri(uri);
    }

    public void addUriPrefix(String prefix) {

        this.uri = formatUri(prefix) + uri;
    }

    public void addUriSuffix(String suffix) {

        this.uri = uri + formatUri(suffix);
    }

    public void addLastUri(String suffix) {

        if (suffix.startsWith(SPLITER_URL)) {
            suffix = suffix.substring(1);
        }
        this.uri = uri + suffix;
    }

    String getUrl() {

        return protocol.name() + "://" + getAddress() + "/" + uri;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public ContentType getContentType() {
        return contentType;
    }

    public void setContentType(ContentType contentType) {
        this.contentType = contentType;
    }

    public Map<String, String> getDefaultHeaders() {
        return defaultHeaders;
    }

    public void addDefaultHeaders(Map<String, String> defaultHeaders) {
        this.defaultHeaders.putAll(defaultHeaders);
    }

    public void addDefaultHeader(String key, String value) {

        this.defaultHeaders.put(key, value);
    }

    public Type getReturnType() {
        return returnType;
    }

    public void setReturnType(Type returnType) {
        this.returnType = returnType;
    }

    public ContentType getResponseContentType() {
        return responseContentType;
    }

    public void setResponseContentType(ContentType responseContentType) {
        this.responseContentType = responseContentType;
    }

    public String getDecodeNode() {
        return decodeNode;
    }

    public void setDecodeNode(String decodeNode) {
        this.decodeNode = decodeNode;
    }

    public ResponseCallback getCallback() {
        return callback;
    }

    public void setCallback(ResponseCallback callback) {
        this.callback = callback;
    }

    public ResponseBodyDecoder getDecoder() {
        return decoder;
    }

    public void setDecoder(ResponseBodyDecoder decoder) {
        this.decoder = decoder;
    }

    public String[] getCondition() {
        return condition;
    }

    public void setCondition(String[] condition) {
        this.condition = condition;
    }

    public RequestMethodInfo toRequestMethodInfo() {

        RequestMethodInfo info = new RequestMethodInfo();
        info.setId(id);
        info.setName(name);
        info.setContentType(contentType);
        info.setUri(uri);
        info.setRequestMethod(method);
        info.setReturnType(returnType);
        info.setResponseContentType(responseContentType);
        info.setDecodeNode(decodeNode);
        info.setCallback(callback);
        info.setCondition(condition);
        info.setDecoder(decoder);
        return info;
    }
}
